package com.pokermind.dse.tcp.client.interactive;

import java.util.ArrayList;
import java.util.List;

/**
 * AI决策质量监控器（V4.28新增）
 * 
 * 功能：
 * 1. 验证AI决策的合理性（胜率、SPR、尺寸、位置）
 * 2. 输出决策评分和警告
 * 3. 提供实时反馈
 * 
 * @author PokerMind Team
 */
public class AIDecisionValidator {
    
    /**
     * 验证AI决策并输出质量评估
     * 
     * @param action 决策行动（fold/call/raise）
     * @param size 下注金额
     * @param position 位置（UTG/MP/CO/BTN/SB/BB）
     * @param street 街道（preflop/flop/turn/river）
     * @param equity 胜率（0-1）
     * @param pot 当前底池
     * @param stack 玩家筹码
     * @param toCall 需跟注金额
     * @param bigBlind 大盲注
     */
    public static void validateAndPrint(
            String action, int size, String position, String street,
            Double equity, Integer pot, Integer stack, Integer toCall, Integer bigBlind) {
        
        List<String> warnings = new ArrayList<>();
        List<String> notes = new ArrayList<>();
        int score = 100; // 满分100
        
        // 1. 胜率检查
        if (equity != null) {
            double gtoThreshold = getGTOThreshold(position, street);
            
            if ("raise".equalsIgnoreCase(action) && equity < gtoThreshold) {
                warnings.add(String.format("胜率%.1f%%低于GTO阈值%.1f%%", equity * 100, gtoThreshold * 100));
                score -= 20;
            } else if ("fold".equalsIgnoreCase(action) && equity > gtoThreshold + 0.05) {
                warnings.add(String.format("胜率%.1f%%较高，fold可能偏紧", equity * 100));
                score -= 10;
            } else {
                notes.add(String.format("胜率%.1f%%合理", equity * 100));
            }
        }
        
        // 2. SPR检查
        if (pot != null && stack != null && pot > 0) {
            double spr = (double) stack / pot;
            
            if (spr < 4 && "fold".equalsIgnoreCase(action) && equity != null && equity > 0.4) {
                warnings.add(String.format("低SPR(%.1f)+高胜率，fold偏保守", spr));
                score -= 15;
            } else if (spr > 15 && "raise".equalsIgnoreCase(action) && size > pot) {
                warnings.add(String.format("高SPR(%.1f)+大尺寸，风险较高", spr));
                score -= 10;
            } else {
                notes.add(String.format("SPR%.1f合理", spr));
            }
        }
        
        // 3. 尺寸检查（翻前）
        if ("preflop".equalsIgnoreCase(street) && size > 0 && bigBlind != null) {
            double bbSize = (double) size / bigBlind;
            
            if (toCall == null || toCall == 0) {
                // Open raise
                if (bbSize < 2.0 || bbSize > 4.0) {
                    warnings.add(String.format("开池尺寸%.1fBB偏离标准(2-4BB)", bbSize));
                    score -= 10;
                } else {
                    notes.add(String.format("开池尺寸%.1fBB标准", bbSize));
                }
            } else {
                // 3-bet or call
                if ("raise".equalsIgnoreCase(action)) {
                    if (bbSize < 6.0 || bbSize > 12.0) {
                        warnings.add(String.format("反加注尺寸%.1fBB偏离标准(6-12BB)", bbSize));
                        score -= 10;
                    } else {
                        notes.add(String.format("反加注尺寸%.1fBB标准", bbSize));
                    }
                }
            }
        }
        
        // 4. 尺寸检查（翻后）
        if (!"preflop".equalsIgnoreCase(street) && size > 0 && pot != null && pot > 0) {
            double potRatio = (double) size / pot;
            
            if (potRatio < 0.25 || potRatio > 1.5) {
                warnings.add(String.format("下注%.0f%%底池偏离常规(25-150%%)", potRatio * 100));
                score -= 10;
            } else {
                notes.add(String.format("尺寸%.0f%%底池合理", potRatio * 100));
            }
        }
        
        // 5. 位置检查
        if ("preflop".equalsIgnoreCase(street) && "raise".equalsIgnoreCase(action)) {
            if (("UTG".equals(position) || "MP".equals(position)) && equity != null && equity < 0.32) {
                warnings.add("早位加注，牌力略弱");
                score -= 15;
            }
        }
        
        // 输出评估结果
        printValidationResult(action, size, score, warnings, notes);
    }
    
    /**
     * 获取GTO胜率阈值
     */
    private static double getGTOThreshold(String position, String street) {
        if (!"preflop".equalsIgnoreCase(street)) {
            return 0.25; // 翻后默认阈值
        }
        
        // 翻前按位置
        return switch (position) {
            case "UTG", "EP" -> 0.35;
            case "MP", "HJ" -> 0.33;
            case "CO" -> 0.30;
            case "BTN" -> 0.25;
            case "SB" -> 0.32;
            case "BB" -> 0.30;
            default -> 0.30;
        };
    }
    
    /**
     * 打印验证结果（V4.28优化：只显示评分，不显示警告理由）
     */
    private static void printValidationResult(String action, int size, int score, 
                                               List<String> warnings, List<String> notes) {
        // 评分等级
        String grade;
        String gradeIcon;
        if (score >= 90) {
            grade = "优秀";
            gradeIcon = "✓";
        } else if (score >= 75) {
            grade = "良好";
            gradeIcon = "✓";
        } else if (score >= 60) {
            grade = "及格";
            gradeIcon = "△";
        } else {
            grade = "需优化";
            gradeIcon = "!";
        }
        
        // V4.28: 只输出评分，不显示警告理由
        System.out.printf("[决策评估] %s %d | 评分: %d/100 (%s)%n", 
                gradeIcon, size, score, grade);
    }
    
    /**
     * 快速验证（从Map数据）
     */
    public static void validateFromMap(java.util.Map<String, Object> aiDecision, GameState state) {
        try {
            String action = (String) aiDecision.get("action");
            String sizeStr = String.valueOf(aiDecision.get("size"));
            int size = 0;
            try {
                size = Integer.parseInt(sizeStr);
            } catch (Exception e) {
                // 忽略
            }
            
            Player currentPlayer = state.getCurrentPlayer();
            String position = currentPlayer.getPosition();
            String street = state.getStreet();
            Integer pot = state.getPot();
            Integer stack = currentPlayer.getStack();
            Integer bigBlind = state.getBigBlind();
            
            // 计算需跟注金额
            int maxBet = state.getPlayers().stream()
                    .mapToInt(Player::getCurrentBet)
                    .max()
                    .orElse(0);
            Integer toCall = maxBet - currentPlayer.getCurrentBet();
            
            // 胜率需要从AI响应中获取（如果有）
            Double equity = null;
            // 注意：当前AI响应中没有胜率字段，这里暂时不检查
            
            validateAndPrint(action, size, position, street, equity, pot, stack, toCall, bigBlind);
        } catch (Exception e) {
            System.out.println("[决策评估] 评估失败: " + e.getMessage());
        }
    }
}

